package com.youbug.kefu.websocket;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.youbug.kefu.constant.ChatConstant;
import com.youbug.kefu.entity.Chat;
import com.youbug.kefu.entity.Message;
import com.youbug.kefu.entity.User;
import com.youbug.kefu.service.IChatService;
import com.youbug.kefu.service.IMessageService;
import com.youbug.kefu.service.IUserService;
import com.youbug.kefu.vo.MessageVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;


/**
 * @author websocket服务
 */
@ServerEndpoint(value = "/online/{userType}/{userId}")
@Component
public class OnlineWebSocket {

    private static final Logger logger = LoggerFactory.getLogger(OnlineWebSocket.class);

    private static List<AgentSessionWrapper> agents = new ArrayList<>();

    private ObjectMapper objectMapper = new ObjectMapper();
    private static Map<Long, Chat> chatMap = new HashMap<>();
    private static Map<Long, Long> clientTochatMap = new HashMap<>();
    private static IUserService userService;
    private static IMessageService messageService;
    private static IChatService chatService;

    private Random random = new Random();

    @Autowired
    public void setChatService(IChatService chatService,IMessageService messageService, IUserService userService) {
        OnlineWebSocket.chatService = chatService;
        OnlineWebSocket.messageService = messageService;
        OnlineWebSocket.userService = userService;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userType") String userType, @PathParam("userId") Long userId) {
        if(ChatConstant.AGENT.equals(userType)){

            QueryWrapper<User> userWp = new QueryWrapper<User>().eq("id", userId);

            userWp.select("username","nick_name");

            User userDb = userService.getOne(userWp);

            agents.add(new AgentSessionWrapper(userId, userDb.getNickName(), session));

        }else if(ChatConstant.CLIENT.equals(userType)){

        }else{
            throw new RuntimeException("不合法的userType用户类型");
        }

    }

    /**
     * 收到客户端消息后调用的方法
     * 后台收到客户端发送过来的消息
     * onMessage 是一个消息的中转站
     * 接受 浏览器端 socket.send 发送过来的 json数据
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session, @PathParam("userType") String userType, @PathParam("userId") Long userId) throws IOException {

        MessageVo msg = objectMapper.readValue(message, MessageVo.class);
        Long chatId = msg.getChatId();
        Message msgEntity = new Message();
        msgEntity.setCreateTime(msg.getCreateTime());

        BeanUtils.copyProperties(msg, msgEntity);

        if(ChatConstant.AGENT.equals(userType)){
            Chat chat = chatMap.get(chatId);
            msgEntity.setSenderName(chat.getAgentName());
            msgEntity.setChatId(chat.getId());
            chat.getClientSession().getBasicRemote().sendText(objectMapper.writeValueAsString(msg));

        }else if(ChatConstant.CLIENT.equals(userType)){

            Chat chat = chatMap.get(chatId);

            if(chat == null){

                chat = chatService.getById(chatId);

                chat.setClientId(userId);
                chat.setClientSession(session);
                chat.setClientName(msg.getClientName());

                chatMap.put(chatId, chat);
                clientTochatMap.put(userId, chatId);

                if(agents.size() == 0){
                    MessageVo temp = new MessageVo();
                    temp.setContent("坐席繁忙,稍后从新发送");
                    temp.setType("text");
                    temp.setSender("agent");

                    session.getBasicRemote().sendText(objectMapper.writeValueAsString(temp));
                }else{
                    AgentSessionWrapper wrapper = agents.get(random.nextInt(agents.size()));
                    chat.setAgentSession(wrapper.getSession());
                    chat.setAgentId(wrapper.getUserId());
                    chat.setAgentName(wrapper.getAgentName());
                    chat.setType("0");
                    chatService.updateById(chat);
                    Message messag = new Message();

                    BeanUtils.copyProperties(msg, messag);
                    String value = objectMapper.writeValueAsString(msg);
                    chat.getAgentSession().getBasicRemote().sendText(value);
                }
                msgEntity.setChatId(chat.getId());
            }else{
                Session agentSession = chat.getAgentSession();

                if (agentSession == null){
                    if(agents.size() == 0){
                        MessageVo temp = new MessageVo();
                        temp.setContent("坐席繁忙,稍后重新发送");
                        temp.setType("text");
                        temp.setSender("agent");
                        session.getBasicRemote().sendText(objectMapper.writeValueAsString(temp));
                    }else{
                        AgentSessionWrapper agentSessionWrapper = agents.get(random.nextInt(agents.size()));
                        chat.setAgentSession(agentSessionWrapper.getSession());
                        chat.setAgentId(agentSessionWrapper.getUserId());
                    }
                }
                chat.getAgentSession().getBasicRemote().sendText(objectMapper.writeValueAsString(msg));
            }
            msgEntity.setSenderName(chat.getClientName());
        }

        msgEntity.setSenderId(userId);

        messageService.save(msgEntity);
        session.getBasicRemote().sendText(objectMapper.writeValueAsString(msg));
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session, @PathParam("userType") String userType, @PathParam("userId") Long userId) {

        if("client".equals(userType)){
            Long chatId = clientTochatMap.get(userId);
            chatMap.remove(chatId);
            clientTochatMap.remove(userId);
            // 客户端断开
            System.out.println("onClose,客户端断开"+userId);
        }else if("agent".equals(userType)){
            for (int i=0;i<agents.size();i++){
                 if(userId.equals(agents.get(i).userId)){
                     AgentSessionWrapper wrapper = agents.get(i);
                     System.out.println("onClose,座席端断开"+userId);

                     agents.remove(agents.get(i));
                 }
            }
        }
    }

    @OnError
    public void onError(Session session, Throwable error, @PathParam("userType") String userType, @PathParam("userId") Long userId) throws IOException {
        System.out.println("onError"+error.getMessage());

        if("client".equals(userType)){
            Long chatId = clientTochatMap.get(userId);
            chatMap.remove(chatId);
            clientTochatMap.remove(userId);
        }
        session.close();
    }
    class AgentSessionWrapper{
        private Long userId;
        private String agentName;
        private Session session;

        public AgentSessionWrapper(Long userId, String agentName, Session session) {
            this.userId = userId;
            this.agentName = agentName;
            this.session = session;
        }

        public Long getUserId() {
            return userId;
        }

        public void setUserId(Long userId) {
            this.userId = userId;
        }

        public String getAgentName() {
            return agentName;
        }

        public void setAgentName(String agentName) {
            this.agentName = agentName;
        }

        public Session getSession() {
            return session;
        }

        public void setSession(Session session) {
            this.session = session;
        }
    }
}
